home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 4
/
Aminet 4 - November 1994.iso
/
aminet
/
comm
/
net
/
dnet2_10_13.lha
/
DNet
/
Amiga
/
Sourcen.lha
/
dnet
/
subs.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-14
|
10KB
|
514 lines
/*
* SUBS.C
*
* DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved.
*
*/
#include "dnet.h"
#include <stdio.h>
#ifdef LATTICE
#include <dos.h>
#endif
#ifndef LATTICE
char *FakeArgs;
long FakeLen;
long FakeGo;
long FakeCLI;
extern char *malloc();
#endif
void dneterror();
typedef struct CommandLineInterface CLI;
/*
* Add the high-level command to the queue of commands to be sent to
* the remote DNET.
*/
void
WriteStream(sdcmd, buf, len, chan)
int sdcmd;
void *buf;
int len;
uword chan;
{
IOSTD *ior = AllocMem(sizeof(IOSTD), MEMF_PUBLIC);
if (DDebug)
printf("WriteStream: cmd %ld buflen %ld chan %ld\n", sdcmd, len, chan);
ior->io_Message.mn_Node.ln_Name = (char *)PKT_REQ;
ior->io_Message.mn_ReplyPort = IOSink;
ior->io_Data = (APTR)AllocMem(len, MEMF_PUBLIC);
ior->io_Length = len;
ior->io_Actual = 0;
ior->io_Command = sdcmd;
ior->io_Error = 0;
ior->io_Message.mn_Node.ln_Pri = (chan > MAXCHAN) ? 126 : Chan[chan].pri;
BMov(buf, ior->io_Data, len);
Enqueue(&TxList, (NODE *)ior);
do_wupdate();
}
/*
* Send a packet to a port. Used to send data/eof/close to channel
* ports, and to relay open requests to server ports.
*/
void
WritePort(port, scmd, buf, len, rettype, unit)
PORT *port;
int scmd;
void *buf;
int len;
int rettype;
int unit;
{
IOSTD *ior = AllocMem(sizeof(IOSTD), MEMF_PUBLIC);
if (DDebug)
printf("WritePort: cmd %ld buflen %ld rt %ld unit %ld\n", scmd, len, rettype, unit);
ior->io_Message.mn_Node.ln_Name = (char *)rettype;
ior->io_Message.mn_ReplyPort = (rettype) ? IOSink : DNetPort;
ior->io_Unit = (struct Unit *)unit;
ior->io_Command = scmd;
ior->io_Error = 0;
ior->io_Data = NULL;
ior->io_Length = 0;
ior->io_Actual = 0;
if (buf) {
ior->io_Data = (APTR)AllocMem(len, MEMF_PUBLIC);
ior->io_Length = len;
BMov(buf, ior->io_Data, len);
}
PutMsg(port, (MSG *)ior);
if (rettype == PKT_REQ)
++NumCon;
}
/*
* ALLOC_CHANNEL()
*
* Allocate a channel. Starting at a random point, find the first
* free channel. Return -1 if no free channels found.
*/
alloc_channel()
{
static ulong ran = 13;
long stamp[3];
uword i;
DateStamp(stamp);
ran = ((ran * 13) + 1) ^ (ran >> 9) + stamp[0] + stamp[1] + stamp[2];
for (i = ran % MAXCHAN; i < MAXCHAN; ++i) {
if (Chan[i].state == 0) {
return((int)i);
}
}
for (i = ran % MAXCHAN; i != 0xFFFF; --i) { /* Fixed 28 September 1988 */
if (Chan[i].state == 0) {
return((int)i);
}
}
return(-1);
}
/*
* Get next node in a linked list. If a pointer to a list base
* is passed, gets the first node in the linked list. Returns
* NULL if no further nodes in the list.
*/
GetNext(node)
NODE *node;
{
NODE *next = node->ln_Succ;
if (*(long *)next)
return((long)next);
return(NULL);
}
/*
* CHKBUF
*
* Generate a two-byte checksum for data. Uses a very simple, but
* effective algorithm.
*/
chkbuf(buf, bytes)
ubyte *buf;
uword bytes;
{
uword i;
ubyte c1,c2;
for (i = c1 = c2 = 0; i < bytes; ++i) {
c1 += buf[i];
c2 += c1;
}
c1 = -(c1 + c2);
return((c1<<8)|c2);
}
void
TimerOpen(req, sink)
IOT *req;
PORT *sink;
{
if (OpenDevice("timer.device", UNIT_VBLANK, (IOR *)req, 0))
dneterror("timer.device");
req->tr_node.io_Message.mn_ReplyPort = sink;
req->tr_node.io_Command = TR_ADDREQUEST;
}
void
TimerClose(req)
IOT *req;
{
CloseDevice((IOR *)req);
req->tr_node.io_Device = NULL;
}
/*
* RUNSERVER
*
* Search the file [S:]DNET.SERVERS for the specified server and
* attempt to LoadSeg()/CreateProc() it. The port number must be
* non-zero (allows commening out lines in DNET.SERVERS), and
* regardless of whether the server is able to DListen(), it must
* perform a small handshake sequence with DNET.
*/
#ifdef LATTICE
static struct ProcID *SvBase;
void
InitServers()
{
SvBase = NULL;
}
void
RunServer(portnum)
uword portnum;
{
FILE *fi;
char buf[128];
char s1[64], s2[64];
long v1;
if (!portnum)
return;
if ((fi = fopen("dnet.servers", "r")) == NULL)
fi = fopen("s:dnet.servers", "r");
if (fi) {
while (fgets(buf, 128, fi)) {
if (sscanf(buf, "%ld %s %s", &v1, s1, s2) == 3 && v1 == portnum)
goto success;
}
fclose(fi);
}
return;
success:
fclose(fi);
{
PROC *myproc;
MSG msg;
struct ProcID *pid = malloc(sizeof(struct ProcID));
int error;
BZero(pid, sizeof(*pid));
error = forkl(s1, "__dnet", "__dnet", NULL, NULL, pid);
if (error < 0) {
printf("Server not found: %s\n", s1);
free(pid);
} else {
myproc = (PROC *)FindTask(NULL);
msg.mn_ReplyPort = &myproc->pr_MsgPort;
msg.mn_Node.ln_Name = s2;
printf("Starting Server: %s proc %08lx ", s1, pid->process);
fflush(stdout);
PutMsg(&pid->process->pr_MsgPort, &msg); /* startup handshake */
WaitPort(&myproc->pr_MsgPort);
(void)GetMsg(&myproc->pr_MsgPort);
puts("started");
fflush(stdout);
pid->nextID = SvBase;
SvBase = pid;
}
}
}
void
DeleteServers()
{
struct ProcID *pid, *pn;
for (pid = SvBase; pid; pid = pn) {
pn = pid->nextID;
for (;;) {
Signal((TASK *)pid->process, SIGBREAKF_CTRL_C);
printf("Waiting for pid %08lx to die\n", pid->process);
if (CheckPort(pid->parent))
break;
Delay(10);
}
wait(pid);
free(pid);
}
}
#else
static MLIST SvList;
void
InitServers()
{
NewList(&SvList);
}
void
RunServer(portnum)
uword portnum;
{
FILE *fi;
char buf[128];
char s1[64], s2[64];
long v1;
long seg;
if (!portnum)
return;
if ((fi = fopen("dnet.servers", "r")) == NULL)
fi = fopen("s:dnet.servers", "r");
if (fi) {
while (fgets(buf, 128, fi)) {
if (sscanf(buf, "%ld %s %s", &v1, s1, s2) == 3 && v1 == portnum)
goto success;
}
fclose(fi);
}
return;
success:
fclose(fi);
if (seg = (long)LoadSeg(s1)) {
PNODE *pnode;
PROC *myproc;
PROC *proc;
char *name;
BSTR oldclicmd;
CLI *cli;
char *fakestr;
MSG msg;
void fakeseg();
printf("Addr: %08lx\n", seg);
myproc = (PROC *)FindTask(NULL);
pnode = AllocMem(sizeof(PNODE), MEMF_PUBLIC);
sprintf(pnode->name, "DNET.SERVER.%ld", portnum);
pnode->seg = seg;
FakeArgs= "__dnet";
FakeLen = 6;
FakeGo = ((long)pnode->seg << 2) + 4;
FakeCLI = (long)myproc->pr_CLI;
printf("Addr: %08lx %08lx\n", seg, FakeGo);
fakestr = malloc(32);
strcpy(fakestr, "\006__dnet");
cli = BTOC(FakeCLI);
oldclicmd = cli->cli_CommandName;
cli->cli_CommandName = CTOB(fakestr);
if (proc = CreateProc(pnode->name, 0, (long)fakeseg >> 2, 4096)) {
proc = (PROC *)((char *)proc - OFFSET(proc,pr_MsgPort));
msg.mn_ReplyPort = &myproc->pr_MsgPort;
msg.mn_Node.ln_Name = s2;
printf("Starting Server: %s %s\n", s1, pnode->name);
PutMsg(&proc->pr_MsgPort, &msg); /* startup handshake */
WaitPort(&myproc->pr_MsgPort);
(void)GetMsg(&myproc->pr_MsgPort);
AddTail(&SvList, pnode);
} else {
printf("Unable to start server: %s %s\n", s1, pnode->name);
FreeMem(pnode, sizeof(PNODE));
}
cli->cli_CommandName = oldclicmd;
free(fakestr);
} else {
printf("Server not found: %s\n", s1);
}
}
void
DeleteServers()
{
PNODE *pnode;
PROC *proc;
while (pnode = (PNODE *)RemHead(&SvList)) {
Forbid();
while (proc = (PROC *)FindTask(pnode->name)) {
Signal(proc, SIGBREAKF_CTRL_C);
Permit();
printf("Waiting for server %s to exit\n", pnode->name);
Forbid();
}
Permit();
UnLoadSeg(pnode->seg);
FreeMem(pnode, sizeof(PNODE));
}
}
#asm
INCLUDE "exec/types.i"
INCLUDE "exec/alerts.i"
INCLUDE "exec/nodes.i"
INCLUDE "exec/lists.i"
INCLUDE "exec/ports.i"
INCLUDE "exec/libraries.i"
INCLUDE "exec/tasks.i"
INCLUDE "exec/memory.i"
INCLUDE "exec/execbase.i"
INCLUDE "libraries/dos.i"
INCLUDE "libraries/dosextens.i"
public _geta4
public _LVOFindTask
nop
nop
nop
nop
_fakeseg:
nop
nop
nop
nop
bsr _geta4
move.l 4,A6
sub.l A1,A1
jsr _LVOFindTask(A6)
move.l D0,A0
move.l _FakeCLI,pr_CLI(A0) ; dummy CLI so Lattice startup doesn't
; croak thinking its a workbench process
move.l _FakeArgs,A0
move.l _FakeLen,D0
move.l _FakeGo,A1
jmp (A1)
#endasm
#endif
/*
* This cleans up as best as possible, but if there are still ACTIVE
* servers or any CLIENTS, this call will not completely get rid of
* them...
*
* Note that this call will KILL any servers automatically started up
* by DNET and then UnLoadSeg() them. If the server has already exited,
* it simply unloads the server's segment.
*/
void
dneterror(str)
char *str;
{
short i;
if (str)
puts(str);
if (DNetPort) {
IOSTD *ior;
Forbid();
while ((ior = (IOSTD *)RemHead(&TxList)) || (ior = (IOSTD *)GetMsg(DNetPort))) {
ior->io_Error = -1;
ReplyMsg((MSG *)ior);
}
DeletePort(DNetPort);
Permit();
DNetPort = NULL;
}
if (Wto.tr_node.io_Device) {
if (Wto_act) {
AbortIO((IOR *)&Wto);
WaitIO((IOR *)&Wto);
Wto_act = 0;
}
TimerClose(&Wto);
}
if (Rto.tr_node.io_Device) {
if (Rto_act) {
AbortIO((IOR *)&Rto);
WaitIO((IOR *)&Rto);
Rto_act = 0;
}
TimerClose(&Rto);
}
if (Cto.tr_node.io_Device) {
if (Cto_act) {
AbortIO((IOR *)&Cto);
WaitIO((IOR *)&Cto);
Cto_act = 0;
}
TimerClose(&Cto);
}
NetClose();
if (IOSink)
DeletePort(IOSink);
IOSink = NULL;
for (i = 0; i < MAXCHAN; ++i) {
if (Chan[i].state != CHAN_FREE && Chan[i].ior) {
Chan[i].ior->io_Error = -1;
Chan[i].state = CHAN_FREE;
ReplyMsg((MSG *)Chan[i].ior);
}
}
DeleteServers();
/*
if (IPCPort)
CloseIPC(IPCPort);
if (DResBase)
CloseLibrary(DResBase);
*/
exit(1);
}
void
fixsignal(port)
PORT *port;
{
if ((long)port->mp_MsgList.lh_Head != (long)&port->mp_MsgList.lh_Tail)
Signal(port->mp_SigTask, 1 << port->mp_SigBit);
}
void
SetTimeouts(baud)
{
WTimeoutVal = ((MAXPKT * 2) * 1000 / (baud / 10 + 1));
RTimeoutVal = ((MAXPKT + 50) * 1000 / (baud / 10 + 1));
WTimeoutVal *= 1000;
RTimeoutVal *= 1000;
}